﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using CasaEngineEditor.Log;

namespace Editor.Sprite2DEditor
{
    /// <summary>
    /// 
    /// </summary>
    public partial class AddSpriteAndAnimForm : Form
    {
        #region Fields

        // a list of the files we'll build into our sprite sheet
        private readonly List<string> m_Files = new List<string>();

        #endregion

        #region Properties

        /// <summary>
        /// Gets
        /// </summary>
        public string[] Files
        {
            get { return m_Files.ToArray(); }
        }

        /// <summary>
        /// Gets
        /// </summary>
        public bool DetectAnimation2D
        {
            get { return checkBoxDetectAnimations.Checked; }
        }

        /// <summary>
        /// Gets
        /// </summary>
        public string PackageName
        {
            get { return comboBoxPackage.SelectedItem as string; }
        }

        #endregion

        #region Constructors

        /// <summary>
        /// 
        /// </summary>
        public AddSpriteAndAnimForm()
        {
            InitializeComponent();

            // set our open file dialog filter based on the valid extensions
            imageOpenFileDialog.Filter = "Image Files|";
            foreach (var ext in Editor.Sprite2DEditor.SpriteSheetPacker.sspack.MiscHelper.AllowedImageExtensions)
                imageOpenFileDialog.Filter += string.Format("*.{0};", ext);
        }

        #endregion

        #region Methods

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonAddDirectory_Click(object sender, EventArgs e)
        {
            FolderBrowserDialog form = new FolderBrowserDialog();
            //form.SelectedPath = GameInfo.Instance.ProjectManager.ProjectPath;

            if (form.ShowDialog(this) == DialogResult.OK)
            {
                AddFilesFromDirectory(form.SelectedPath);
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void addImageBtn_Click(object sender, EventArgs e)
        {
            // show our file dialog and add all the resulting files
            if (imageOpenFileDialog.ShowDialog() == DialogResult.OK)
                AddFiles(imageOpenFileDialog.FileNames);
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void removeImageBtn_Click(object sender, EventArgs e)
        {
            // build a list of files to be removed
            List<string> filesToRemove = new List<string>();
            foreach (var i in listBox1.SelectedItems)
                filesToRemove.Add((string)i);

            // remove the files from our internal list
            m_Files.RemoveAll(filesToRemove.Contains);

            // remove the files from our list box
            filesToRemove.ForEach(f => listBox1.Items.Remove(f));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void clearBtn_Click(object sender, EventArgs e)
        {
            // clear both lists
            m_Files.Clear();
            listBox1.Items.Clear();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paths"></param>
        private void AddFilesFromDirectory(string path)
        {
            // if the path is a directory, add all files inside the directory
            if (Directory.Exists(path))
            {
                AddFiles(Directory.GetFiles(path, "*", SearchOption.AllDirectories));
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="paths"></param>
        private void AddFiles(IEnumerable<string> paths)
        {
            foreach (var path in paths)
            {
                // make sure the file is an image
                if (!Editor.Sprite2DEditor.SpriteSheetPacker.sspack.MiscHelper.IsImageFile(path))
                    continue;

                // prevent duplicates
                if (IsFileNameValid(path) == false)
                {
                    string msg = "The file (" + path + ") already exist or an other file as the same name.";
                    MessageBox.Show(this, msg, "Warning", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    LogManager.Instance.WriteLineWarning(msg);
                    continue;
                }

                // add to both our internal list and the list box
                m_Files.Add(path);
                listBox1.Items.Add(path);
            }
        }

        /// <summary>
        /// Check if the file as the same name that the files already added
        /// </summary>
        /// <param name="path">full path of the file</param>
        /// <returns>true if the name is unic</returns>
        private bool IsFileNameValid(string path_)
        {
            if (string.IsNullOrWhiteSpace(path_))
            {
                throw new ArgumentNullException("SpriteSheetPackerForm.IsFileNameValid() : path_ is null");
            }

            path_ = Path.GetFileName(path_);

            foreach (string f in m_Files)
            {
                if (Path.GetFileName(f).Equals(path_) == true)
                {
                    return false;
                }
            }

            return !m_Files.Contains(path_);
        }

        // determines if a directory contains an image we can accept
        public static bool DirectoryContainsImages(string directory)
        {
            foreach (var file in Directory.GetFiles(directory, "*", SearchOption.AllDirectories))
            {
                if (Editor.Sprite2DEditor.SpriteSheetPacker.sspack.MiscHelper.IsImageFile(file))
                {
                    return true;
                }
            }

            return false;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_DragEnter(object sender, DragEventArgs e)
        {
            // if this drag is not for a file drop, ignore it
            if (!e.Data.GetDataPresent(DataFormats.FileDrop))
                return;

            // figure out if any the files being dropped are images
            bool imageFound = false;
            foreach (var f in (string[])e.Data.GetData(DataFormats.FileDrop))
            {
                // if the path is a directory and it contains images...
                if (Directory.Exists(f) && DirectoryContainsImages(f))
                {
                    imageFound = true;
                    break;
                }

                // or if the path itself is an image
                if (Editor.Sprite2DEditor.SpriteSheetPacker.sspack.MiscHelper.IsImageFile(f))
                {
                    imageFound = true;
                    break;
                }
            }

            // if an image is being added, we're going to copy them. otherwise, we don't accept them.
            e.Effect = imageFound ? DragDropEffects.Copy : DragDropEffects.None;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void listBox1_DragDrop(object sender, DragEventArgs e)
        {
            // add all the files dropped onto the list box
            if (e.Data.GetDataPresent(DataFormats.FileDrop))
                AddFiles((string[])e.Data.GetData(DataFormats.FileDrop));
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void buttonOK_Click(object sender, EventArgs e)
        {
            if (m_Files.Count == 0)
            {
                MessageBox.Show(this, "Please select at least one image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            if (comboBoxPackage.SelectedItem == null
                || string.IsNullOrWhiteSpace(comboBoxPackage.SelectedItem as string) == true)
            {
                MessageBox.Show(this, "Please select at least one image", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            DialogResult = DialogResult.OK;
            Close();
        }

        #endregion
    }
}
